package com.yenlien.traceyun.common.utils;


import java.io.*;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.net.URL;
import java.net.URLConnection;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;


/**
 * 工具类
 */
public class Tools {

    public static final SimpleDateFormat DATE_TIME_FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    public static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd");

    public static final DateTimeFormatter DATE_TIME_BIAS_FORMATTER = DateTimeFormatter.ofPattern("yyyy/MM/dd");
    public static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd");
    public static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

    public static String getDateParamUnix(int len) {
        return System.currentTimeMillis() + random(len);
    }

    public static String getYearStr() {
        return (new SimpleDateFormat("yyyy")).format(new Date());
    }

    public static String getMonthStr() {
        return (new SimpleDateFormat("MM")).format(new Date());
    }

    public static String getCurrentTime() {
        return DATE_TIME_FORMAT.format(new Date());
    }

    public static String getDateYearMonth() {
        return (new SimpleDateFormat("yyyy-MM")).format(new Date());
    }

    public static String getDateYearMonthDate() {
        return (new SimpleDateFormat("yyyy-MM-dd")).format(new Date());
    }

    public static String getDate() {
        return (new SimpleDateFormat("yyyyMMdd")).format(new Date());
    }

    public static String getDateAll() {
        return (new SimpleDateFormat("yyyyMMddHHmmss")).format(new Date());
    }

    /**
     * 获取某月天数
     *
     * @param date
     * @return
     */
    public static int getDaysOfMonth(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        return calendar.getActualMaximum(Calendar.DAY_OF_MONTH);
    }

    //获取本周第一天
    public static String getWeekStart() {
        Calendar cal = Calendar.getInstance();
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");
        cal.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY); // 获取本周一的日期  
        return df.format(cal.getTime());
    }

    //获取本周最后一天
    public static String getWeekLast() {
        Calendar cal = Calendar.getInstance();
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");
        cal.set(Calendar.DAY_OF_WEEK, Calendar.SUNDAY);// 这种输出的是上个星期周日的日期，因为老外那边把周日当成第一天
        cal.add(Calendar.WEEK_OF_YEAR, 1);// 增加一个星期，才是我们中国人理解的本周日的日期  
        return df.format(cal.getTime());
    }

    public static String getCurrentTimePlusMinute(int second) {
        Calendar afterTime = Calendar.getInstance();
        afterTime.add(Calendar.SECOND, second);
        Date afterDate = (Date) afterTime.getTime();
        return Tools.DATE_TIME_FORMAT.format(afterDate);
    }

    public static String getDatePlusDay(String type, String createDate, int day) {
        String temp = "";
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        try {
            Date date = sdf.parse(createDate);
            Calendar cl = Calendar.getInstance();
            cl.setTime(date);
            if (("DATE").equals(type)) {
                cl.add(Calendar.DATE, day);
            } else if (("MINUTE").equals(type)) {
                cl.add(Calendar.MINUTE, day);
            } else if (("SECOND").equals(type)) {
                cl.add(Calendar.SECOND, day);
            }
            temp = sdf.format(cl.getTime());
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return temp;
    }

    /**
     * @param type
     * @param createDate
     * @param day
     * @return
     */
    public static String getDatePlusTime(String type, String createDate, int day) {
        String temp = "";
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        try {
            Date date = Tools.DATE_TIME_FORMAT.parse(createDate);
            Calendar cl = Calendar.getInstance();
            cl.setTime(date);
            if (("DATE").equals(type)) {
                cl.add(Calendar.DATE, day);
            } else if (("MINUTE").equals(type)) {
                cl.add(Calendar.MINUTE, day);
            } else if (("SECOND").equals(type)) {
                cl.add(Calendar.SECOND, day);
            }
            temp = Tools.DATE_TIME_FORMAT.format(cl.getTime());
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return temp;
    }

    /**
     * 获取每月第一天
     *
     * @return
     */
    public static String getFirstDay() {
        return (new SimpleDateFormat("yyyy-MM")).format(new Date()) + "-01 00:00:00";
    }

    /**
     * 获取每月第一天
     *
     * @return
     */
    public static String getCurrentDay() {
        return (new SimpleDateFormat("yyyy-MM-dd")).format(new Date()) + " 23:59:59";
    }

    /**
     * 获取当月的 天数
     */
    public static int getCurrentMonthDay() {

        Calendar a = Calendar.getInstance();
        a.set(Calendar.DATE, 1);
        a.roll(Calendar.DATE, -1);
        int maxDate = a.get(Calendar.DATE);
        return maxDate;
    }

    /**
     * 根据年 月 获取对应的月份 天数
     */
    public static int getDaysByYearMonth(int year, int month) {

        Calendar a = Calendar.getInstance();
        a.set(Calendar.YEAR, year);
        a.set(Calendar.MONTH, month - 1);
        a.set(Calendar.DATE, 1);
        a.roll(Calendar.DATE, -1);
        int maxDate = a.get(Calendar.DATE);
        return maxDate;
    }

    //===============================金额转换开始===============================================================
    /**
     * 汉语中数字大写
     */
    private static final String[] CN_UPPER_NUMBER = {"零", "壹", "贰", "叁", "肆", "伍", "陆", "柒", "捌", "玖"};
    /**
     * 汉语中货币单位大写，这样的设计类似于占位符
     */
    private static final String[] CN_UPPER_MONETRAY_UNIT = {"分", "角", "元", "拾", "佰", "仟", "万", "拾", "佰", "仟", "亿", "拾", "佰", "仟", "兆", "拾", "佰", "仟"};
    /**
     * 特殊字符：整
     */
    private static final String CN_FULL = "整";
    /**
     * 特殊字符：负
     */
    private static final String CN_NEGATIVE = "负";
    /**
     * 金额的精度，默认值为2
     */
    private static final int MONEY_PRECISION = 2;
    /**
     * 特殊字符：零元整
     */
    private static final String CN_ZEOR_FULL = "零元" + CN_FULL;

    /**
     * 把输入的金额转换为汉语中人民币的大写
     *
     * @param numberOfMoney 输入的金额
     * @return 对应的汉语大写
     */
    public static String number2CNMontrayUnit(BigDecimal numberOfMoney) {
        StringBuffer sb = new StringBuffer();
        int signum = numberOfMoney.signum();
        // 零元整的情况
        if (signum == 0) {
            return CN_ZEOR_FULL;
        }
        //这里会进行金额的四舍五入
        long number = numberOfMoney.movePointRight(MONEY_PRECISION)
                .setScale(0, 4).abs().longValue();
        // 得到小数点后两位值
        long scale = number % 100;
        int numUnit = 0;
        int numIndex = 0;
        boolean getZero = false;
        // 判断最后两位数，一共有四中情况：00 = 0, 01 = 1, 10, 11
        if (!(scale > 0)) {
            numIndex = 2;
            number = number / 100;
            getZero = true;
        }
        if ((scale > 0) && (!(scale % 10 > 0))) {
            numIndex = 1;
            number = number / 10;
            getZero = true;
        }
        int zeroSize = 0;
        while (true) {
            if (number <= 0) {
                break;
            }
            // 每次获取到最后一个数
            numUnit = (int) (number % 10);
            if (numUnit > 0) {
                if ((numIndex == 9) && (zeroSize >= 3)) {
                    sb.insert(0, CN_UPPER_MONETRAY_UNIT[6]);
                }
                if ((numIndex == 13) && (zeroSize >= 3)) {
                    sb.insert(0, CN_UPPER_MONETRAY_UNIT[10]);
                }
                sb.insert(0, CN_UPPER_MONETRAY_UNIT[numIndex]);
                sb.insert(0, CN_UPPER_NUMBER[numUnit]);
                getZero = false;
                zeroSize = 0;
            } else {
                ++zeroSize;
                if (!(getZero)) {
                    sb.insert(0, CN_UPPER_NUMBER[numUnit]);
                }
                if (numIndex == 2) {
                    if (number > 0) {
                        sb.insert(0, CN_UPPER_MONETRAY_UNIT[numIndex]);
                    }
                } else if (((numIndex - 2) % 4 == 0) && (number % 1000 > 0)) {
                    sb.insert(0, CN_UPPER_MONETRAY_UNIT[numIndex]);
                }
                getZero = true;
            }
            // 让number每次都去掉最后一个数
            number = number / 10;
            ++numIndex;
        }
        // 如果signum == -1，则说明输入的数字为负数，就在最前面追加特殊字符：负
        if (signum == -1) {
            sb.insert(0, CN_NEGATIVE);
        }
        // 输入的数字小数点后两位为"00"的情况，则要在最后追加特殊字符：整
        if (!(scale > 0)) {
            sb.append(CN_FULL);
        }
        return sb.toString();
    }
    //===============================金额转换结束===============================================================

    /**
     * 加
     */
    public static String addtr(String v1, String v2) {
        DecimalFormat df = new DecimalFormat("0.00");
        BigDecimal b1 = new BigDecimal(v1);
        BigDecimal b2 = new BigDecimal(v2);
        String b3 = df.format(b1.add(b2));
        if (b3.contains(".00")) {
            b3 = b3.substring(0, b3.indexOf("."));
        }
        return b3;
    }

    /**
     * 减
     */
    public static String subtr(String v1, String v2) {
        DecimalFormat df = new DecimalFormat("0.00");
        BigDecimal b1 = new BigDecimal(v1);
        BigDecimal b2 = new BigDecimal(v2);
        String b3 = df.format(b1.subtract(b2));
        if (b3.contains(".00")) {
            b3 = b3.substring(0, b3.indexOf("."));
        }
        return b3;
    }


    /**
     * 乘
     */
    public static String multiply(String v1, String v2) {
        DecimalFormat df = new DecimalFormat("0.00");
        BigDecimal b1 = new BigDecimal(v1);
        BigDecimal b2 = new BigDecimal(v2);
        String b3 = df.format(b1.multiply(b2));
        if (b3.contains(".00")) {
            b3 = b3.substring(0, b3.indexOf("."));
        }
        return b3;
    }

    /**
     * 除
     */
    public static String division(String v1, String v2) {
        DecimalFormat df = new DecimalFormat("0.00");
        BigDecimal b1 = new BigDecimal(v1);
        BigDecimal b2 = new BigDecimal(v2);
        String b3 = df.format(b1.divide(b2, 2, RoundingMode.HALF_DOWN));
        if (b3.contains(".00")) {
            b3 = b3.substring(0, b3.indexOf("."));
        }
        return b3;
    }

    /**
     * 除
     */
    public static Double chu(double v1, double v2) {
        BigDecimal b1 = new BigDecimal(v1);
        BigDecimal b2 = new BigDecimal(v2);
        return b1.divide(b2, 2, RoundingMode.HALF_DOWN).doubleValue();
    }

    /**
     * 乘
     */
    public static String multiply(String v1, String v2, String v3) {
        BigDecimal b1 = new BigDecimal(v1);
        BigDecimal b2 = new BigDecimal(v2);
        BigDecimal b3 = new BigDecimal(v3);
        return b1.multiply(b2).multiply(b3).toString();
    }

    public static String accuracy(double num, double total, int scale) {
        DecimalFormat df = (DecimalFormat) NumberFormat.getInstance();
        //可以设置精确几位小数
        df.setMaximumFractionDigits(scale);
        //模式 例如四舍五入
        df.setRoundingMode(RoundingMode.HALF_UP);
        double accuracy_num = num / total * 100;
        return df.format(accuracy_num) + "%";
    }

    /**
     * 保留小数
     *
     * @param v1     原始值
     * @param places 几位小数
     * @return
     */
    public static String reserve(String v1, Integer places) {
        BigDecimal bg = new BigDecimal(v1);
        return bg.setScale(places, BigDecimal.ROUND_HALF_UP).toString();
    }

    public static String getRandom(int n) {
        Random random = new Random();
        StringBuffer valSb = new StringBuffer();
        String charStr = "0123456789abcdefghijklmnopqrstuvwxyz";
        int charLength = charStr.length();
        for (int i = 0; i < n; i++) {
            int index = random.nextInt(charLength);
            valSb.append(charStr.charAt(index));
        }
        return valSb.toString();
    }

    /**
     * 随机长度
     */
    public static String random(int len) {
        long lng = new Random().nextLong();
        if (lng < 0) {
            lng = lng * (-1);
        }
        String lngStr = "" + lng;
        if (lngStr.length() < len) {
            lngStr += random(len - lngStr.length());
        } else {
            lngStr = lngStr.substring(0, len);
        }
        return lngStr;
    }

    /**
     * 根据.切取字符串
     */
    public static String getStrend(String str, int num) {
        String[] strVale = str.split("[.]");
        str = strVale[num];
        return str;
    }

    /**
     * md5加密
     */
    public static String getMD5Str(String str) {
        MessageDigest messageDigest = null;
        try {
            messageDigest = MessageDigest.getInstance("MD5");
            messageDigest.reset();
            messageDigest.update(str.getBytes("UTF-8"));
        } catch (NoSuchAlgorithmException e) {
            System.out.println("NoSuchAlgorithmException caught!");
            System.exit(-1);
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }

        byte[] byteArray = messageDigest.digest();
        StringBuffer md5StrBuff = new StringBuffer();
        for (int i = 0; i < byteArray.length; i++) {
            if (Integer.toHexString(0xFF & byteArray[i]).length() == 1)
                md5StrBuff.append("0").append(
                        Integer.toHexString(0xFF & byteArray[i]));
            else
                md5StrBuff.append(Integer.toHexString(0xFF & byteArray[i]));
        }
        return md5StrBuff.toString();
    }

    public static String formatMac(String mac) {
        String resultmac = mac.substring(0, 2) + "-" + mac.substring(3, 5)
                + "-" + mac.substring(6, 8) + "-" + mac.substring(9, 11) + "-"
                + mac.substring(12, 14) + "-" + mac.substring(15, 17);
        return resultmac.toUpperCase();
    }


    /**
     * post请求
     */
    public static String sendPost(String str) throws IOException {
        URL url = new URL(str);
        URLConnection connection = url.openConnection();
        connection.setConnectTimeout(1000 * 10);// 设置连接超时
        connection.setReadTimeout(1000 * 10);// 设置读取超时
        connection.setDoOutput(true);
        OutputStreamWriter out = new OutputStreamWriter(
                connection.getOutputStream(), "UTF-8");

        out.write("url=" + str);
        out.flush();
        out.close();
        String sCurrentLine = "";
        String sTotalString = "";
        InputStream l_urlStream = connection.getInputStream();
        BufferedReader l_reader = new BufferedReader(new InputStreamReader(
                l_urlStream, "UTF-8"));
        while ((sCurrentLine = l_reader.readLine()) != null) {
            sTotalString += sCurrentLine + "\r\n";
        }
        return sTotalString;
    }


    //判断对象是否为空
    public static boolean isObjectNull(Object obj) {
        if (obj != null && !"".equals(obj)) {
            return false;
        } else {
            return true;
        }
    }

    //判断字符串是否只包含数字和字母(位数限制)
    public static boolean isNumAndStr(String str, int minLength, int maxLength) {
        Pattern pattern = Pattern.compile("^[A-Za-z0-9]{" + minLength + "," + maxLength + "}$");
        Matcher matcher = pattern.matcher(str);
        return matcher.matches();
    }

    //判断字符串是否只包含数字、字母和下划线
    public static boolean isNumAndStrAnd_(String str) {
        Pattern pattern = Pattern.compile("^\\w+$");
        Matcher matcher = pattern.matcher(str);
        return matcher.matches();
    }

    //判断特殊字符
    public static boolean isSpecial_all(String str) {
        Pattern pattern = Pattern.compile("^[^\\`\\~\\^\\|\\;\\:\"\\'\\?\\\\]*$");
        Matcher matcher = pattern.matcher(str);
        return matcher.matches();
    }

    //判断特殊字符_textarea
    public static boolean isSpecial_textarea(String str) {
        Pattern pattern = Pattern.compile("^[^\"\\<\\>\\/\\\\]*$");
        Matcher matcher = pattern.matcher(str);
        return matcher.matches();
    }

    //判断整数_0到任意数字
    public static boolean isNumberZero(String str) {
        Pattern pattern = Pattern.compile("^\\d*$");
        Matcher matcher = pattern.matcher(str);
        return matcher.matches();
    }

    //判断整数_不能为0
    public static boolean isNumber(String str) {
        Pattern pattern = Pattern.compile("^[1-9]{1}\\d*$");
        Matcher matcher = pattern.matcher(str);
        return matcher.matches();
    }

    //判断小数_整数最长7位,最多两位小数
    public static boolean isDecimal_7(String str) {
        Pattern pattern = Pattern.compile("(^0|[1-9]{1}\\d{0,6})(\\.\\d{1,2})?$");
        Matcher matcher = pattern.matcher(str);
        return matcher.matches();
    }

    //判断小数_整数最长11位,最多两位小数
    public static boolean isDecimal_11(String str) {
        Pattern pattern = Pattern.compile("(^0|[1-9]{1}\\d{0,10})(\\.\\d{1,2})?$");
        Matcher matcher = pattern.matcher(str);
        return matcher.matches();
    }

    //判断图片地址
    public static boolean isImg(String str) {
        Pattern pattern = Pattern.compile("(?i).+?\\.(jpg|gif|bmp|png|jpeg)");
        Matcher matcher = pattern.matcher(str);
        return matcher.matches();
    }

    //判断手机号码
    public static boolean isMobilePhone(String str) {
        Pattern pattern = Pattern.compile("^1((3|5|7|8){1}\\d{1}|70)\\d{8}$");
        Matcher matcher = pattern.matcher(str);
        return matcher.matches();
    }

    //判断座机号码
    public static boolean isOfficePhone(String str) {
        Pattern pattern = Pattern.compile("^\\d{7,8}$|^\\d{3,4}-\\d{7,8}$|^\\d{3,4}-\\d{7,8}-\\d{1,4}$");
        Matcher matcher = pattern.matcher(str);
        return matcher.matches();
    }

    //判断邮箱
    public static boolean isEmail(String str) {
        Pattern pattern = Pattern.compile("^\\w+([-+.]\\w+)*@\\w+([-.]\\w+)*\\.\\w+([-.]\\w+)*$");
        Matcher matcher = pattern.matcher(str);
        return matcher.matches();
    }

    //判断身份证
    public static boolean isIdcard(String str) {
        Pattern pattern = Pattern.compile("^(^[1-9]\\d{7}((0\\d)|(1[0-2]))(([0|1|2]\\d)|3[0-1])\\d{3}$)|(^[1-9]\\d{5}[1-9]\\d{3}((0\\d)|(1[0-2]))(([0|1|2]\\d)|3[0-1])((\\d{4})|\\d{3}[Xx])$)$");
        Matcher matcher = pattern.matcher(str);
        return matcher.matches();
    }

    //判断时间  istype 1代表默认年月日时分秒 2代表年月日
    public static boolean isValidDate(String str, int istype) {
        boolean convertSuccess = true;
        String datestr = "";
        if (istype == 1) {
            datestr = "yyyy-MM-dd HH:mm:ss";
        } else {
            datestr = "yyyy-MM-dd";
        }
        SimpleDateFormat format = new SimpleDateFormat(datestr);

        try {
            format.setLenient(false);
            format.parse(str);
        } catch (Exception e) {
            System.out.println("转换时间格式异常");
            convertSuccess = false;
        }
        return convertSuccess;
    }

    //判断长度
    public static boolean isLength(String str, int start, int end) {
        if (str.length() < start || str.length() > end) {
            return false;
        }
        return true;
    }

    //判断长度
    public static boolean isLength(String str, int start) {
        if (str.length() != start) {
            return false;
        }
        return true;
    }

    /**
     * 去掉小数点后无效的0
     *
     * @param str
     * @return
     */
    public static String removeNoValidZero(String str) {
        if (str.indexOf(".") > 0) {
            //正则表达
            str = str.replaceAll("0+?$", "");//去掉后面无用的零
            str = str.replaceAll("[.]$", "");//如小数点后面全是零则去掉小数点
        }
        return str;
    }

    public static List<String> getListBySplit(String resources) {
        return Arrays.asList(resources.split(","));
    }
}
